
	//*****************************************************************
	// Microsoft Scripting Libary 1.0a
	// Remote Scripting utilities for client.
	//
	//	The Remote Scripting utilities for the client consist of
	//	three public methods and the RSCallObject definition. 
	//	The public methods are RSEnableRemoteScripting, RSExecute 
	//	and RSGetASPObject. The RSCallObject is returned from any 
	//	remote scripting call and provides status and return value.
	//
	// Copyright 1999 Microsoft Corporation. All Rights Reserved.
	//*****************************************************************
	
	//*****************************************************************
	// function RSEnableRemoteScripting()
	//	This function enables the remote scripting proxy.
	//*****************************************************************
	function RSEnableRemoteScripting(codebase)
	{
		MSRS = new _MSRS_Object();
		if (typeof(codebase) == 'undefined')
		{	// assume applet is in _ScriptLibrary directory off the webroot
			var secondSlash, path;
			codebase = '';
			if ((secondSlash = (path = window.location.pathname).indexOf('/',1)) != -1)
				codebase = path.substring(0,secondSlash);
			codebase += '/_ScriptLibrary';
		}
		document.write('<' + 'APPLET name=RSAspProxyApplet codebase=' + codebase + ' code=RSProxy.class height=0 width=0></APPLET>');	
	}

	//*****************************************************************
	// function RSExecute(url,method,p1 ... pn,cb,ecb,context)
	//	This is the function by which remote scripting calls are made.
	//	The caller provides the following :
	//		url		: url to the asp file containing remote script
	//		method	: name of the method to be invoked
	//		p1...pn	: any parameters required by the method
	//		cb		: an optional callback routine for async.
	//		ecb		: an optional error callback routine for async.
	//		context	: an optional user context
	//*****************************************************************
	function RSExecute(url,method)
	{
		var cb, ecb, context;
		var params = new Array;
		var pn = 0;
		var len = RSExecute.arguments.length;
		for (var i=2; i < len; i++)
			params[pn++] = RSExecute.arguments[i];
		
		return MSRS.invokeMethod(url,method,params);
	}

	//*****************************************************************
	// function RSGetASPObject(url)
	//	This function returns a server object for an ASP file
	//	described by its public_description.
	//*****************************************************************
	function RSGetASPObject(url)
	{
		var cb, ecb, context;
		var params = new Array;
		var request = MSRS.startRequest(url,'GetServerProxy',params,cb,ecb,context);
		//alert(request.data);	// USED FOR DEBUG
		if (request.status == MSRS_COMPLETED)
		{
			var server = request.return_value;
			if (typeof(Function) == 'function')
			{
				for (var name in server)
					server[name] = Function('return MSRS.invokeMethod(this.location,"' +  name + '",this.' + name + '.arguments);');
			}
			else
			{	// JavaScript 1.0 does not support Function  ( IE3.0 )
				for (var name in server)
					server[name] = eval('function t(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pA,pB,pC,pD,pE,pF) { return MSRS.invokeMethod(this.location,"' + name + '",this.' + name + '.arguments);} t');
			}
			server.location = url;
			return server;
		}
		alert('Failed to create ASP object for : ' + url);
		return null;
	}

	//*****************************************************************
	// function RSCallObject(cb,ecb,context)
	//
	//	The RSCallObject is returned for every remote scripting
	//	invocation. It contains the return value and status.
	//
	//		id				:	unique id of request
	//		status			:	status of request, one of 
	//								MSRS_COMPLETED
	//								MSRS_FAIL
	//								MSRS_PENDING
	//								MSRS_PARTIAL
	//		message			:	message associated with status
	//		data			:	raw data returned from server
	//		return_value	:	evaluated value returned from server
	//		callback		:	user provided callback ( optional )
	//		error_callback	:	user provided callback ( optional )
	//		context			:	user provided context ( optional )
	//
	//*****************************************************************
	function RSCallObject(cb,ecb,context)
	{
		this.id = MSRS.nextRequestID++;
		this.status = MSRS_PENDING;
		this.message = '';
		this.data = '';
		this.return_value = '';
		
		this.callback = cb;
		this.error_callback = ecb;
		this.context = context;

		this.wait = RSCallObject_wait;
		this.cancel = RSCallObject_cancel;

		MSRS.requestList[this.id] = this;
	}

	//*****************************************************************
	// function RSCallObject_wait()
	//
	//	The RSCallObject_wait method can be called from an asynchronous
	//  request to wait for it to complete.  If the request has finished
	//  this call returns immediately.
	//
	//		this = RSCallObject instance to wait for
	//*****************************************************************
    function RSCallObject_wait()
	{
		if (this.status != MSRS_PENDING)
			return;
		while (true)
		{	// wait synchronously for response
			if (MSRS.rsapplet.waitForResponse())
			{
				if (MSRS.rsapplet.hasResponse())
				{
					var rid = MSRS.rsapplet.getRequestID();
					MSRS.handleResponse(rid);
					// DO NOT CHANGE THIS CODE
					// Solves Java to Script discrepancies between IE3 and Navigator
					var strrid = String(rid);
					if (strrid == null)
						strrid = rid;
					if (strrid == this.id)	
						break;				// this response completed			
				}
			}
			else
			{
				this.status = MSRS_FAIL;
				this.message = 'Request not handled.'
				break;
			}
		}
	}

	//*****************************************************************
	// function RSCallObject_cancel()
	//
	//	The RSCallObject_cancel method can be called from an 
	//	asynchronous request to cancel it.  If the request has 
	//	finished this call returns immediately.
	//
	//		this = RSCallObject instance to cancel
	//*****************************************************************
    function RSCallObject_cancel()
	{
		if (this.status == MSRS_PENDING)
		{
			MSRS.rsapplet.cancelRequest(this.id);
			this.status = MSRS_FAIL;
			this.message = 'Request cancelled.'
		}
	}

	//*** PRIVATE IMPLEMENTATION BELOW ********************************
	//*** PRIVATE IMPLEMENTATION BELOW ********************************
	//*** PRIVATE IMPLEMENTATION BELOW ********************************
	//*****************************************************************
	//
	// Remote Scripting Object --  private implementation
	//
	//	The following code is private glue code that contains the
	//	implementation of a JSObject to enable remote scripting
	//	functionality on the client. This private object is utilized
	//	by the public Remote Scripting methods defined above.
	//
	//*****************************************************************
	//*****************************************************************

	//*****************************************************************
	// function _MSRS_Object
	//
	//	This is the JSObject that interacts with the RSAspProxy
	//	applet to synchronously/asynchronously retrieve data via
	//	an ASP file.
	//*****************************************************************
	//var MSRS = new _MSRS_Object();
	function _MSRS_Object()
	{
		MSRS_FAIL = -1;
		MSRS_COMPLETED = 0;
		MSRS_PENDING = 1;
		MSRS_PARTIAL = 2;

		this.REQUEST_MODE_COMPLETE = 0;
		this.POLLING_PERIOD = 100;

		this.pollID = 0;
		this.pollCount = 0;
		this.nextRequestID = 1;
		this.requestList = new Array;
		this.rsapplet = null;

		this.startRequest = _MSRS_startRequest;
		this.invokeMethod = _MSRS_invokeMethod;
		this.handleResponse = _MSRS_handleResponse;
		this.evaluateRequest = _MSRS_evaluateRequest;
		this.setRequestPoll = _MSRS_setRequestPoll;
		this.requestPollHandler = _MSRS_requestPollHandler;
		this.buildURL = _MSRS_buildURL;
	}

	//*****************************************************************
	// function _MSRS_startRequest(url,method,args,cb,ecb,context)
	//
	//	This is key function for initiating a request for data.
	//	The url to the ASP file is required. The callback, 
	//	error_callback, and user context parameters are optional.
	//*****************************************************************
	function _MSRS_startRequest(url,method,args,cb,ecb,context)
	{
		var request = new RSCallObject(cb,ecb,context);
		if (this.rsapplet == null)
		{
			if (typeof(document.RSAspProxyApplet) == 'object')
				this.rsapplet = document.RSAspProxyApplet;
			else if (typeof(document.thisForm) == 'object' && typeof(document.thisForm.RSAspProxyApplet) == 'object')
				this.rsapplet = document.thisForm.RSAspProxyApplet;
			else
			{
				errmsg = 'ERROR:\nCannot locate proxy which supports Remote Scripting.\nWas RSEnableRemoteScripting method invoked?';
				request.status = MSRS_FAIL;
				request.message = errmsg; 
				alert(errmsg);
			}
		}

		if (request.status != MSRS_FAIL)
		{
			url = this.buildURL(url,method,args);
			url_context = window.location.href; // May not be 'window.location.pathname'
			this.rsapplet.startRequest(request.id,url_context,url,this.REQUEST_MODE_COMPLETE);
			if (typeof(cb) == 'function')
			{
				if (this.pollCount++ == 0)
					this.setRequestPoll();
			}
			else
			{	// wait synchronously for response
				request.wait();
			}
		}
		return request;
	}

	//*****************************************************************
	// function _MSRS_invokeMethod(url,method,args)
	//	This is the function by which remote scripting calls are 
	//	via a server object retrieved with the GetASPObject call.
	//	The caller provides the following :
	//		url		: url to the asp 
	//		method	: name of the method to be invoked
	//		args	: an array containing method parameters
	//				  and the optional cb, ecb, context parameters
	//*****************************************************************
	function _MSRS_invokeMethod(url,method,args)
	{
		var cb, ecb, context;
		var params = new Array;
		var pn = 0;
		var i = 0;
		for (var i=0; i < args.length; i++)
		{
			if (typeof(args[i]) == 'function')
			{
				pn = -1;	// no more params
				if (typeof(cb) == 'undefined')
					cb = args[i];
				else
					ecb = args[i];
			}
			else if (pn != -1)
			{
				params[pn++] = args[i];
			}
			else
				context = args[i];
		}

		return MSRS.startRequest(url,method,params,cb,ecb,context);
	}

	//*****************************************************************
	// function _MSRS_handleResponse(requestid)
	//
	//	This function will handle the response for a given request.
	//	If the response is complete or failed, then the associated
	//	request object will be updated and the appropriate callback
	//	invoked, if provided.
	//	NOTE: incremental data retrieval is not yet supported
	//*****************************************************************
	function _MSRS_handleResponse(requestid)
	{
		var request = this.requestList[requestid];
        if (typeof(request) == 'undefined')
		{
            alert('Unknown request id.');
			return;
		}

        request.status = this.rsapplet.getStatus();
        if (request.status == MSRS_COMPLETED)
		{
			request.data = this.rsapplet.getData();
			request.message = this.rsapplet.getMessage();
			this.evaluateRequest(request);
			if (request.status == MSRS_FAIL)
			{	
				if (typeof(request.error_callback) == 'function')
				{
					this.pollCount--;
					request.error_callback(request);
				}
				else
					alert('Remote Scripting Error\n' + request.message);
			}
			else
			{
				if (typeof(request.callback) == 'function')
				{
					this.pollCount--;
					request.callback(request);
				}
			}
			this.rsapplet.endResponse();
			this.requestList[request.id] = null;
		}
        else if (request.status == MSRS_FAIL)
		{
			request.message = this.rsapplet.getMessage();
			if (typeof(request.error_callback) == 'function')
			{
				this.pollCount--;
				request.error_callback(request);
			}
			this.rsapplet.endResponse();
			this.requestList[request.id] = null;
		}
        else if (request.status == MSRS_PARTIAL)
		{	// not handling partial data retrieval yet
		}
        else if (request.status == MSRS_PENDING)
		{	// do nothing
		}
	}

	//*****************************************************************
	// function _MSRS_evaluateRequest(request)
	//
	//	This function evaluates the data returned to the request. 
	//	Marshalled jscript objects are re-evaluated on the client.
	//*****************************************************************
	function _MSRS_evaluateRequest(request)
	{
		var data = request.data;
		var start_index = 0;
		var end_index = 0;
		var start_key = '<' + 'RETURN_VALUE';
		var end_key = '<' + '/RETURN_VALUE>';

		if ((start_index = data.indexOf(start_key)) != -1)
		{
			var data_start_index = data.indexOf('>',start_index) + 1;
			end_index = data.indexOf(end_key,data_start_index);
			if (end_index == -1) 
				end_index = data.length;
			var metatag = data.substring(start_index,data_start_index);
			if (metatag.indexOf('TYPE=SIMPLE') != -1)
			{
				request.return_value = unescape(data.substring(data_start_index,end_index));
				//alert('TYPE=SIMPLE:\n' + data);	// USED FOR DEBUG
			}
			else if (metatag.indexOf('TYPE=EVAL_OBJECT') != -1)
			{
				request.return_value = data.substring(data_start_index,end_index);
				//alert('TYPE=EVAL_OBJECT:\n' + data);	// USED FOR DEBUG
				request.return_value = eval(unescape(request.return_value));
			}
			else if (metatag.indexOf('TYPE=ERROR') != -1)
			{
				request.status = MSRS_FAIL;
				request.message = unescape(data.substring(data_start_index,end_index));		
			}
		}
		else
		{
			request.status = MSRS_FAIL;
			request.message = 'REMOTE SCRIPTING ERROR: Page invoked does not support remote scripting.';			
		}
	}

	//*****************************************************************
	// function _MSRS_setRequestPoll()
	//
	//	Due to limitations in calling back into JScript from a worker
	//	thread of an applet, a polling mechanism is used to determine
	//	when a request has been completed. This function sets up
	//	a timer to kick the requestPollHandler at a later time.
	//*****************************************************************
	function _MSRS_setRequestPoll()
	{
		this.pollID = window.setTimeout('MSRS.requestPollHandler()',this.POLLING_PERIOD,'javascript');
	}

	//*****************************************************************
	// function _MSRS_requestPollHandler()
	//
	//	Due to limitations in calling back into JScript from a worker
	//	thread of an applet, a polling mechanism is used to determine
	//	when a request has been completed. This function is the 
	//	handler which is kicked by a timer. It polls the applet to
	//	see if a response to a prior request is available.
	//*****************************************************************
	function _MSRS_requestPollHandler()
	{
        while (this.rsapplet.hasResponse())
        {
			this.handleResponse(this.rsapplet.getRequestID());
		}
        if (this.pollCount != 0)
            this.setRequestPoll();
	}

	//*****************************************************************
	// function _MSRS_buildURL(url,method,args)
	//
	//	This builds the proper url entry point into the ASP page
	//	such that the intended server method with parameters gets
	//	invoked.
	//*****************************************************************
	function _MSRS_buildURL(url,method,args)
	{
		if (url == '') url = window.location.pathname;
		if (typeof(method) == 'string')
		{
			url += '?_method=' + method;
			url += '&_mtype=execute';
			var params = '&pcount=0';
			if (typeof(args) != 'undefined' && args.length)
			{	// add parameters
				params = '&pcount=' + args.length 
				for (var i = 0; i < args.length; i++) 
				{
					var arg = args[i];
					params += '&p' + i + '=' + escape(arg);
				}
			}
			url += params;
		}
		return url;
	}

